package com.jhf.youke.order.domain.service;

import com.jhf.youke.core.ddd.AbstractDomainService;
import com.jhf.youke.core.entity.PageQuery;
import com.jhf.youke.core.entity.Pagination;
import com.jhf.youke.core.entity.User;
import com.jhf.youke.core.utils.IdGen;
import com.jhf.youke.core.utils.StringUtils;
import com.jhf.youke.order.domain.converter.OrderConverter;
import com.jhf.youke.order.domain.converter.OrderListConverter;
import com.jhf.youke.order.domain.exception.OrderException;
import com.jhf.youke.order.domain.gateway.OrderRepository;
import com.jhf.youke.order.domain.model.Do.OrderDo;
import com.jhf.youke.order.domain.model.Do.OrderListDo;
import com.jhf.youke.order.domain.model.dto.OrderDto;
import com.jhf.youke.order.domain.model.po.OrderListPo;
import com.jhf.youke.order.domain.model.po.OrderPo;
import com.jhf.youke.order.domain.model.vo.OrderListVo;
import com.jhf.youke.order.domain.model.vo.OrderVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;


/**
 * @author RHJ
 */
@Service
public class OrderService extends AbstractDomainService<OrderRepository, OrderDo, OrderVo> {


    @Resource
    OrderConverter orderConverter;

    @Resource
    OrderListService orderListService;

    @Resource
    OrderListConverter orderListConverter;

    @Override
    public boolean update(OrderDo entity) {
        OrderPo orderPo = orderConverter.do2Po(entity);
        orderPo.preUpdate();
        return repository.update(orderPo);
    }

    @Override
    public boolean updateBatch(List<OrderDo> doList) {
        List<OrderPo> poList = orderConverter.do2PoList(doList);
        return repository.updateBatch(poList);
    }

    @Override
    public boolean delete(OrderDo entity) {
        OrderPo orderPo = orderConverter.do2Po(entity);
        return repository.delete(orderPo);
    }

    @Override
    public boolean deleteBatch(List<Long> idList) {
        return repository.deleteBatch(idList);
    }

    @Override
    public boolean insert(OrderDo entity) {
        entity.computeFee();
        OrderPo orderPo = orderConverter.do2Po(entity);
        if(entity.getItemList() !=null && !entity.getItemList().isEmpty()){
            orderListService.insertBatch(entity.getItemList(),entity.getId());
        }
        orderPo.preInsert();
        return repository.insert(orderPo);
    }

    @Override
    public boolean insertBatch(List<OrderDo> doList) {
        List<OrderPo> poList = orderConverter.do2PoList(doList);
        OrderPo.getInsertListId(poList);
        return repository.insertBatch(poList);
    }

    @Override
    public Optional<OrderVo> findById(Long id) {
        Optional<OrderPo> orderPo =  repository.findById(id);
        OrderVo orderVo = orderConverter.po2Vo(orderPo.orElse(new OrderPo()));
        return Optional.ofNullable(orderVo);

    }

    /**
     * 带详情的查询
     * **/
    public Optional<OrderVo> detailById(Long id) {
        Optional<OrderPo> orderPo =  repository.findById(id);
        OrderVo orderVo = orderConverter.po2Vo(orderPo.orElse(new OrderPo()));
        List<OrderListPo> orderListPos = orderListService.getListByOrderId(id);
        List<OrderListVo> itemList = orderListConverter.po2VoList(orderListPos);
        orderVo.setItemList(itemList);
        return Optional.ofNullable(orderVo);
    }

    @Override
    public boolean remove(Long id) {
        return repository.remove(id);
    }

    @Override
    public boolean removeBatch(List<Long> idList) {
        return repository.removeBatch(idList);
    }

    @Override
    public List<OrderVo> findAllMatching(OrderDo entity) {
        OrderPo orderPo = orderConverter.do2Po(entity);
        List<OrderPo>orderPoList =  repository.findAllMatching(orderPo);
        return orderConverter.po2VoList(orderPoList);
    }


    @Override
    public Pagination<OrderVo> selectPage(OrderDo entity){
        OrderPo orderPo = orderConverter.do2Po(entity);
        PageQuery<OrderPo> pageQuery = new PageQuery<>(orderPo,entity.getCurrentPage(), entity.getPageSize(), entity.getQuerySort());
        pageQuery.setSort("id");
        Pagination<OrderPo> pagination = repository.selectPage(pageQuery);
        return new Pagination<>(pagination.getPageNum(),pagination.getPageSize(),pagination.getTotalSize(),
                orderConverter.po2VoList(pagination.getList()));
    }


    public Boolean completed(OrderDo entity){
        Optional<OrderPo> order =  repository.findById(entity.getId());
        OrderDo orderDo = orderConverter.po2Do(order.orElse(new OrderPo()));
        orderDo.completed();
        OrderPo orderPo = orderConverter.do2Po(orderDo);
        return  repository.update(orderPo);

    }

    public Boolean confirm(OrderDo entity){
        Optional<OrderPo> order =  repository.findById(entity.getId());
        OrderDo orderDo = orderConverter.po2Do(order.orElse(new OrderPo()));
        orderDo.confirm();
        OrderPo orderPo = orderConverter.do2Po(orderDo);
        return  repository.update(orderPo);
    }

    public Boolean deliverGoods(OrderDo entity){
        Optional<OrderPo> order =  repository.findById(entity.getId());
        OrderDo orderDo = orderConverter.po2Do(order.orElse(new OrderPo()));
        orderDo.deliverGoods();
        OrderPo orderPo = orderConverter.do2Po(orderDo);
        return  repository.update(orderPo);
    }

    public Boolean termination(OrderDo entity){
        Optional<OrderPo> order =  repository.findById(entity.getId());
        OrderDo orderDo = orderConverter.po2Do(order.orElse(new OrderPo()));
        orderDo.termination();
        OrderPo orderPo = orderConverter.do2Po(orderDo);
        return  repository.update(orderPo);
    }

    /** 订单支付 **/
    public Boolean paid(OrderDo entity){
        Optional<OrderPo> order =  repository.findById(entity.getId());
        OrderDo orderDo = orderConverter.po2Do(order.orElse(new OrderPo()));
        orderDo.paid();
        OrderPo orderPo = orderConverter.do2Po(orderDo);
        return  repository.update(orderPo);
    }

    @Transactional(rollbackFor = Exception.class)
    public OrderPo videoSave(Map<String,Object> productRelease, User user) {
        Long productReleaseId = StringUtils.toLong(productRelease.get("id"));
        //检查用户是否已购买此视频
        List<OrderPo> list =  repository.getPaidByProductReleaseId(productReleaseId, user.getId());
        if(list.size() > 0){
            throw new OrderException("已购买此商品");
        }
        OrderDo orderDo = new OrderDo(productRelease, user);
        OrderPo orderPo = orderConverter.do2Po(orderDo);
        orderPo.preInsert();
        repository.insert(orderPo);

        OrderListDo listDo = new OrderListDo( productRelease, orderPo.getId());
        orderListService.insert(listDo);
        return orderPo;
    }

    /**
     * 视频订单重新支付
     * @param orderId
     * @param user
     * @return
     */
    public OrderVo videoAgainPay(Long orderId, User user) {
        Optional<OrderPo> orderPo =  repository.findById(orderId);

        OrderListDo param = new OrderListDo();
        param.setOrderId(orderId);
        List<OrderListVo> list = orderListService.findAllMatching(param);

        OrderDo orderDo = new OrderDo();
        orderDo.validateVideoAgainPay(orderPo);
        //检查用户是否已购买此视频
        List<OrderPo> orderPoList =  repository.getPaidByProductReleaseId(list.get(0).getProductReleaseId(), user.getId());
        orderDo.validateVideoAgainPay(orderPoList);

        //重新生成订单支付编码
        orderPo.get().setCode(IdGen.id().toString());

        OrderPo updateOrderPo = new OrderPo();
        updateOrderPo.setId(orderPo.get().getId());
        updateOrderPo.setCode(orderPo.get().getCode());
        repository.update(updateOrderPo);

        OrderVo orderVo = orderConverter.po2Vo(orderPo.get());
        orderVo.setProductName(list.get(0).getProductName());
        return orderVo;
    }

    public boolean videoOrderPayNotify(String code) {
        OrderPo param = new OrderPo();
        param.setCode(code);
        List<OrderPo> list = repository.findAllMatching(param);
        OrderDo orderDo = new OrderDo();
        orderDo.videoPaid(list);
        OrderPo orderPo = orderConverter.do2Po(orderDo);
        return repository.update(orderPo);
    }

    public Integer isBuyProductRelease(Long productReleaseId, User user) {
        //检查用户是否已购买此视频
        List<OrderPo> orderPoList =  repository.getPaidByProductReleaseId(productReleaseId, user.getId());
        if(orderPoList.size() > 0){
            return 1;
        }
        return 0;
    }

    public Pagination<OrderVo> getVideoPageList(OrderDto dto) {
        return repository.getVideoPageList(dto);
    }

}

